package com.changpei.common.utils;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.BeanWrapper;
import org.springframework.beans.BeanWrapperImpl;
import org.springframework.util.ObjectUtils;

import java.lang.reflect.Field;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 *
 *
 * @author Way on 2021/8/9
 */
@Slf4j
public class BeanUtil {

    private static final Pattern HUMP_PATTERN = Pattern.compile("[A-Z]");

    /**
     * <p>Title: collectionCopy</p>
     * <p>Description: list中对象的copy</p>
     *
     * @param source
     * @param clazz
     * @return
     * @throws Exception
     */
    public static <T> List<T> collectionCopy(Collection<?> source, Class<T> clazz) {
        if (ObjectUtils.isEmpty(source)) {
            return new ArrayList<>();
        } else {
            List<T> list = new ArrayList<>();
            try {
                for (Object obj : source) {
                    T target = clazz.getDeclaredConstructor().newInstance();
                    BeanUtils.copyProperties(obj, target);
                    list.add(target);
                }
            } catch (Exception e) {
                log.info("属性拷贝失败：{}", e.getMessage());
                return new ArrayList<>();
            }
            return list;
        }
    }

    /**
     * 只添加有值的数据
     *
     * @param obj
     * @return
     */
    public static Map<String, Object> objectToMap(Object obj) {
        Map<String, Object> map = new LinkedHashMap<>();
        if (ObjectUtils.isEmpty(obj)) {
            return new LinkedHashMap<>();
        }
        Class<?> clazz = obj.getClass();
        try {
            for (Field field : clazz.getDeclaredFields()) {
                // 开启私有属性访问权限
                field.setAccessible(true);
                String fieldName = field.getName();

                // 过滤序列化属性
                if (!fieldName.startsWith("serial")) {
                    Object value = field.get(obj);
                    // 过滤空属性
                    if (!ObjectUtils.isEmpty(value)) {
                        map.put(fieldName, value);
                    }
                }
            }
        } catch (Exception e) {
            log.info("对象转为Map失败：{}", e.getMessage());
            e.printStackTrace();
        }
        return map;
    }

    /**
     * 驼峰命名转为下划线
     *
     * @param str
     * @return
     */
    public static String humpToLine(String str) {
        Matcher matcher = HUMP_PATTERN.matcher(str);
        StringBuffer sb = new StringBuffer();
        while (matcher.find()) {
            matcher.appendReplacement(sb, "_" + matcher.group(0).toLowerCase());
        }
        matcher.appendTail(sb);
        return sb.toString();
    }

    /**
     * 获取所有字段为null的属性名
     * 用于BeanUtils.copyProperties()拷贝属性时，忽略空值
     * @param source
     * @return
     */
    public static String[] getNullPropertyNames(Object source) {
        final BeanWrapper src = new BeanWrapperImpl(source);
        java.beans.PropertyDescriptor[] pds = src.getPropertyDescriptors();

        Set<String> emptyNames = new HashSet<>();
        for (java.beans.PropertyDescriptor pd : pds) {
            Object srcValue = src.getPropertyValue(pd.getName());
            if (ObjectUtils.isEmpty(srcValue)) {
                emptyNames.add(pd.getName());
            }
        }
        String[] result = new String[emptyNames.size()];
        return emptyNames.toArray(result);
    }

}
